﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

using System.IO;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Kenly.ChineseSegment.Core
{
    internal class SerializationUtility
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SerializeToXml(string filePath, object target)
        {
            if (!IsValidSerializeArgs(filePath, target))
            {
                return false;
            }

            try
            {
                XmlSerializerFactory xmlSerializerFactory = new XmlSerializerFactory();
                XmlSerializer xmlSerializer = xmlSerializerFactory.CreateSerializer(target.GetType(), target.GetType().Name);
                SerializeToXml(filePath, target, xmlSerializer);
                return true;
            }
            catch(Exception ex)
            {
                throw new ApplicationException("Serialize xml file failed.", ex);
            }
        }

        private static void SerializeToXml(string filePath, object target, XmlSerializer xmlSerializer)
        {
            Stream stream = new FileStream(filePath, FileMode.OpenOrCreate);
            xmlSerializer.Serialize(stream, target);
            stream.Close();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="targetType"></param>
        /// <returns></returns>
        public static object DeserializeFromXml(string filePath, Type targetType)
        {
            if (!IsValidDeserializeArgs(filePath, targetType))
            {
                return null;
            }

            try
            {
                XmlSerializerFactory xmlSerializerFactory = new XmlSerializerFactory();
                XmlSerializer xmlSerializer = xmlSerializerFactory.CreateSerializer(targetType, targetType.Name);
                object obj = DeserializeFromXml(filePath, xmlSerializer);
                return obj;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Deserialize xml file failed.", ex);
            }

        }

        private static object DeserializeFromXml(string filePath, XmlSerializer xmlSerializer)
        {
            Stream stream = new FileStream(filePath, FileMode.Open);
            object obj = xmlSerializer.Deserialize(stream);
            stream.Close();
            return obj;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static bool SerializeToBin(string filePath, object target)
        {
            if (!IsValidSerializeArgs(filePath, target))
            {
                return false;
            }

            try
            {
                BinaryFormatter formatter=new BinaryFormatter();

                SerializeObject(filePath, target, formatter);
                return true;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Serialize bin file failed.", ex);
            }
        }

       
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="targetType"></param>
        /// <returns></returns>
        public static object DeserializeFromBin(string filePath, Type targetType)
        {
            if (!IsValidDeserializeArgs(filePath, targetType))
            {
                return null;
            }

            try
            {
                BinaryFormatter formatter = new BinaryFormatter();

                object obj = DeserializeObject(filePath, formatter);
                return obj;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Deserialize bin file failed.", ex);
            }

        }

        private static void SerializeObject(string filePath, object target, IFormatter formatter)
        {
            Stream stream = new FileStream(filePath, FileMode.OpenOrCreate);
            formatter.Serialize(stream, target);
            stream.Close();
        }

        private static object DeserializeObject(string filePath,IFormatter formatter)
        {
            Stream stream = new FileStream(filePath, FileMode.Open);
            object obj = formatter.Deserialize(stream);
            stream.Close();
            return obj;
        }

        private static bool IsValidSerializeArgs(string filePath, object target)
        {
            if (target == null)
            {
                return false;
            }
            if (string.IsNullOrEmpty(filePath))
            {
                return false;
            }

            return true;
        }

        private static bool IsValidDeserializeArgs(string filePath, Type targetType)
        {
            if (targetType == null)
            {
                return false;
            }

            if (!Utility.IsValidFile(filePath))
            {
                return false;
            }

            return true;
        }


    }
}
